package com.atguigu.juc.jmm;

/**
 * @author yanglin
 * @create 2024-01-11 9:06 星期四
 * description:
 */
public class JMMDemo {
    /**
     * JMM是一种抽象的概念，并不真实存在，它仅仅描述的是一组约定或规范，通过这组规范定义了程序中各个变量的读写访问方式并决定一个线程
     * 对共享变量的写入何时以及如何变成另一个线程可见，关键技术点都是围绕多线程的原子性，可见性和有序性展开的
     * 
     * 原则：
     *  JMM的关键技术点都是围绕多线程的原子性，可见性和有序性展开的
     *  
     * 能干吗？
     *  1、通过JMM来实现线程和主内存之间的抽象关系
     *  2、屏蔽各个硬件平台和操作系统的内存访问差异以实现让Java程序在各种平台下都能达到一致的内存访问效果
     *  
     * 三大特性：
     *  可见性：是指当一个线程修改了某一个共享变量的值，其他线程是否立即知道该改变，JMM规定了所有的变量都存储在主内存中
     *  原子性：指一个操作是不可以被打断的，即多线程环境下，操作不能被其他线程干扰
     *  有序性：
     *  
     *  指令重排：对于一个线程的执行代码而言，我们总是习惯性的认为代码的执行总是从上到下的，有序执行。但为了提升性能，编译器和处理器
     *          通常会对指令序列进行重新排序。Java规范规定JVM线程内部维持顺序化语义，即只要程序的最终结果和它的顺序化执行的结果
     *          相等，那么指令的执行顺序可以和代码的顺序不一致，此过程叫指令重排
     *      指令重排可以保证串行语义一致，但不保证多线程间的语义也一致（即：可能产生脏读）
     *      
     * 总结：
     *  1、定义的所有共享变量都存储在物理主内存中
     *  2、每个线程都有自己独立的工作内存，里面保存该线程使用到的变量的副本（主内存中该变量的一份拷贝）
     *  3、线程对共享变量所有的操作都必须现在线程自己的工作内存中进行，后在写会主内存，不能直接从主内存中读写
     *  4、不同线程之间也无法直接访问其他线程的工作内存中的变量，线程间变量值的传递需要通过主内存来完成
     *  
     *  
     * 多线程先行发生原则：（happens-before）
     *      在JMM中，如果一个操作执行的结果需要对另一个操作可见性或者代码重排序，那么这两个操作之间必须存在happens-before(先行发生)原则
     *      逻辑上的先后关系
     * 总原则：
     *      如果一个操作happens-before另一个操作，那么第一个操作结果将对第二个操作可见，而且第一个操作的执行顺序排在第二个操作之前
     *      如果两个操作之间存在happens-before关系，并不意味着一定要按照happens-before原则指定的顺序来执行。如果排序之后的执行结果
     *      与按照happens-before关系来执行的结果一致，那么这种重排序并不非法。
     *  8条原则：
     *      1、次序规则：一个线程内按照代码顺序，写在前面的操作先行发生于写在后面的操作
     *      2、锁定规则：一个unLock操作先行发生与后面（指时间上的先后）对同一锁的lock操作
     *      3、volatile变量规则：对一个volatile变量的写操作先行发生于后面对这个变量的读操作，前面的写操作对后面的读操作是可见的。
     *      4、传递规则：如果操作A先行发生于操作B，而操作B又先行发生于操作C，则可以得出操作A先行发生于操作C
     *      5、线程启动规则（Thread Start Rule）：Thread对象的start()方法先行发生于此线程的每一个动作
     *      6、线程中断规则（Thread Interruption Rule）：对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
     *                                                  可以通过Thread.interrupted()检测到是否发生中断，也就是说需要先调用
     *                                                  interrupt()方法设置过中断标志位，才能够检测到发生中断
     *      7、线程终止规则（Thread Termination Rule）：线程中断的所有操作都先行发生于对此线程的终止检测，我们可以通过isAlive()等手段
     *                                               检测线程是否已经终止执行
     *      8、对象终结规则（Finalizer Rule）：一个对象的初始化完成（构造函数执行结束）先行发生于它的finalize()方法的开始
     */
    
    
    
}
